import Axios, { type AxiosRequestConfig } from 'axios'
import type { ResponseType } from './types.d'
import { checkStatus } from './checkStatus'

/** axios基础配置 */
const config: AxiosRequestConfig = {
  baseURL: import.meta.env.VITE_PREFIX,
  timeout: 10000,
  headers: {
    Accept: 'application/json, txt/plan, */*', // 告诉服务器希望收到的数据类型
    'Content-Type': 'application/json; charset=utf-8', // 告诉服务器发送的请求体的数据个数
    'X-Requested-with': 'XMLHttpRequest' // 告诉服务器使用的是ajax发送的请求
  }
}

/** 网络请求类 */
class HttpRequest {
  /** axios实例对象 */
  private static readonly axiosInstance = Axios.create(config)

  constructor() {
    /** 在类实例化的时候初始化拦截器 */
    this.httpInterceptorsRequest()
    this.httpInterceptorsResponse()
  }

  /** 请求拦截器 */
  private httpInterceptorsRequest(): void {
    HttpRequest.axiosInstance.interceptors.request.use((config) => {
      /** 请求发送出去之前做点什么 */
      return config
    })
  }

  /** 响应拦截器 */
  private httpInterceptorsResponse(): void {
    HttpRequest.axiosInstance.interceptors.response.use(
      (response) => {
        /** 请求成功结束数据之前做点什么 */
        return response
      },
      (error) => {
        /** 请求成功发出且服务器也响应了状态码，但状态代码超出了 2xx 的范围。 */
        checkStatus(error.response.status)
      }
    )
  }

  /**
   * @description 通用请求方法
   * @param { AxiosRequestConfig } config 请求的配置
   * @returns {Promise<T>}
   */
  public reqeust<T>(config: AxiosRequestConfig): Promise<T> {
    return new Promise((resolve, reject) => {
      HttpRequest.axiosInstance
        .request<ResponseType<T>>(config)
        .then(({ data: { result: res } }) => {
          resolve(res)
        })
        .catch((err) => {
          reject(err)
        })
    })
  }

  /**
   * @description GET请求方法
   * @param { string } url 请求的url地址
   * @param { any } params 请求的查询参数
   * @param { AxiosRequestConfig } requestConfig 请求的其他配置
   * @returns {Promise<T>}
   */
  public get<T>(url: string, params?: any, requestConfig?: AxiosRequestConfig): Promise<T> {
    /** 请求配置 */
    const config = {
      method: 'GET',
      url,
      params,
      ...requestConfig
    }

    return this.reqeust<T>(config)
  }

  /**
   * @description POST请求方法
   * @param url 请求url地址
   * @param data 携带在请求体的参数
   * @param requestConfig 其他配置
   * @returns {Promise<T>}
   */
  public post<T>(url: string, data?: any, requestConfig?: AxiosRequestConfig): Promise<T> {
    /** 请求配置 */
    const config = {
      method: 'POST',
      url,
      data,
      ...requestConfig
    }

    return this.reqeust<T>(config)
  }

  /**
   * @description PUT请求方法
   * @param url 请求url地址
   * @param data 携带在请求体的参数
   * @param requestConfig 其他配置
   */
  public put<T>(url: string, data?: any, requestConfig?: AxiosRequestConfig): Promise<T> {
    /** 请求配置 */
    const config = {
      method: 'PUT',
      url,
      data,
      ...requestConfig
    }

    return this.reqeust<T>(config)
  }

  /**
   * @description delete请求方法
   * @param url 请求url地址
   * @param params 查询参数
   * @param reqeustConfig 其他配置
   */
  public delete<T>(url: string, params?: any, requestConfig?: AxiosRequestConfig): Promise<T> {
    /** 请求配置 */
    const config = {
      method: 'DELETE',
      url,
      params,
      ...requestConfig
    }

    return this.reqeust<T>(config)
  }
}

export const http = new HttpRequest()
